package com.duowei.diandan.db;

import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import android.util.Log;

import com.duowei.diandan.app.SqlServerDateTime;
import com.duowei.diandan.bean.food.FoodCate;
import com.duowei.diandan.bean.food.FoodImpl;
import com.duowei.diandan.bean.food.FoodItem;
import com.duowei.diandan.bean.food.Meal;
import com.duowei.diandan.bean.food.MealChildGroup;
import com.duowei.diandan.bean.food.Single;
import com.duowei.diandan.bean.food.SingleAndMeals;
import com.duowei.diandan.bean.food.SingleGroup;
import com.duowei.diandan.bean.food.Taste;
import com.duowei.diandan.constant.MealPosition;
import com.duowei.diandan.constant.MenuItemType;
import com.duowei.diandan.constant.Settings;
import com.duowei.diandan.db.entry.Cxdmxxx;
import com.duowei.diandan.db.entry.Dmjyxmsslb;
import com.duowei.diandan.db.entry.Dmpzsd;
import com.duowei.diandan.db.entry.Dpzsz;
import com.duowei.diandan.db.entry.Jyxmsz;
import com.duowei.diandan.db.entry.Mzszjbxx;
import com.duowei.diandan.db.entry.Mzszmxxx;
import com.duowei.diandan.db.entry.Tcmc;
import com.duowei.diandan.db.entry.Tcsd;

import org.joda.time.LocalDateTime;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Observable;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;

public class FoodMenu extends Observable {
    private static final String TAG = "FoodMenu";

    private static final FoodMenu INSTANCE = new FoodMenu();
    private AppDatabase mDb;
    private Handler mHandler;

    private Map<FoodCate, List<FoodItem>> mMenuMap = new TreeMap<>((o1, o2) -> {
        Dmjyxmsslb d1 = o1.getDmjyxmsslb();
        Dmjyxmsslb d2 = o2.getDmjyxmsslb();
        if (d1 != null && d1.getXl() != null && d2 != null && d2.getXl() != null) {
            if (d1.getXl() > d2.getXl()) {
                return 1;
            } else if (d1.getXl() < d2.getXl()) {
                return -1;
            }
        }

        return 1;
    });

    /** 存储所有的单品 */
    private List<Single> mSingleAllList = new ArrayList<>();

    /** 存储所有的套餐 */
    private List<Meal> mMealAllList = new ArrayList<>();

    /** 存储所有的单品组 */
    private List<SingleGroup> mSingleGroupAllList = new ArrayList<>();

    private Comparator<FoodItem> mXlComparator = (Comparator<FoodItem>) (o1, o2) -> {
        if (o1 != null && o1.getXl() != null && o2 != null && o2.getXl() != null) {
            if (o1.getXl() > o2.getXl()) {
                return 1;
            } else if (o1.getXl() < o2.getXl()) {
                return -1;
            }
        }

        return 1;
    };

    private FoodMenu() {
        mDb = AppDatabase.getDatabase();
        mHandler = new Handler(Looper.getMainLooper());
    }

    public static FoodMenu getInstance() {
        return INSTANCE;
    }

    @WorkerThread
    public void updateData() {
        mMenuMap.clear(); // 清空菜单列表
        mSingleAllList.clear(); // 清空单品列表
        mMealAllList.clear();   // 清空套餐列表
        mSingleGroupAllList.clear(); // 清空单品组列表

        // 单品
        List<Dmjyxmsslb> dmjyxmsslbList = mDb.dmjyxmsslbDao().findBySfxs("0");

        for (int i = 0; i < dmjyxmsslbList.size(); i++) {
            Dmjyxmsslb d = dmjyxmsslbList.get(i);

            List<FoodItem> foodItemList = new ArrayList<>();

            // 单品数据处理
            List<Jyxmsz> jyxmszList1;
            if (Settings.ONLY_SHOW_BY21) {
                jyxmszList1 = mDb.jyxmszDao().findByLbbmBy21(d.getLbbm());
            } else {
                jyxmszList1 = mDb.jyxmszDao().findByLbbm(d.getLbbm());
            }
            //
            for (Jyxmsz j : jyxmszList1) {

                FoodItem item = new FoodItem();
                j.setDmjyxmsslb(d);

                FoodImpl food = createFood(j);
                if (food != null) {
                    item.setFood(food);
                    foodItemList.add(item);
                }
            }

            // 单品组数据处理
            List<Jyxmsz> jyxmszList;
            if (Settings.ONLY_SHOW_BY21) {
                jyxmszList = mDb.jyxmszDao().findSingleGroupByLbbmBy21(d.getLbbm());
            } else {
                jyxmszList = mDb.jyxmszDao().findSingleGroupByLbbm(d.getLbbm());
            }

            for (Jyxmsz jyxmsz : jyxmszList) {
                jyxmsz.setDmjyxmsslb(d);

                Dpzsz dpzsz = mDb.dpzszDao().findByBm(jyxmsz.getBy1());
                if (dpzsz != null) {

                    FoodItem item = new FoodItem();

                    List<Jyxmsz> jyxmszList2;
                    if (Settings.ONLY_SHOW_BY21) {
                        jyxmszList2 = mDb.jyxmszDao().findByBy1By21(jyxmsz.getBy1());
                    } else {
                        jyxmszList2 = mDb.jyxmszDao().findByBy1(jyxmsz.getBy1());
                    }

                    if (jyxmszList2.size() > 0) {
                        List<FoodImpl> foodList = new ArrayList<>();
                        for (Jyxmsz j : jyxmszList2) {
                            FoodImpl food = createFood(j);
                            if (food != null) {
                                foodList.add(food);
                            }
                        }

                        if (foodList.size() > 0) {
                            SingleGroup singleGroup = new SingleGroup(dpzsz.getBm() + "_dpz", dpzsz.getNr(), jyxmsz.getXl(), foodList);
                            item.setFood(singleGroup);
                            foodItemList.add(item);

                            mSingleGroupAllList.add(singleGroup); // 保存单品组
                        }
                    }
                }
            }

            //
            if (foodItemList.size() > 0) {
                FoodItem header = new FoodItem();
                header.setMenuItemType(MenuItemType.TYPE_HEADER);
                header.setName(d.getLbmc());
                foodItemList.add(0, header);

                FoodCate cate = new FoodCate(d);

                header.setCateUuid(cate.getHeaderUuid());

                mMenuMap.put(cate, foodItemList);

                //
                Collections.sort(foodItemList, mXlComparator);
            }
        }

        // 套餐
        if (MealPosition.ALONE == Settings.MEAL_POSITION) {
            List<String> lbmcList = mDb.tcmcDao().findDistinctLbmc();

            for (int i = 0; i < lbmcList.size(); i++) {
                String lbmc = lbmcList.get(i);

                List<Tcmc> tcmcList = mDb.tcmcDao().findByLbmc(lbmc);

                List<FoodItem> foodItemList = new ArrayList<>();
                for (Tcmc tcmc : tcmcList) {
                    Tcsd main = mDb.tcsdDao().findMainByXmbh(tcmc.getXmbh());

                    //
                    if (main != null && Settings.ONLY_SHOW_BY21) {
                        Jyxmsz jyxmsz = mDb.jyxmszDao().findByXmbh(main.getXmbh1());
                        if (!"1".equals(jyxmsz.getBy21())) {
                            main = null;
                        }
                    }
                    //
                    if (main != null) {
                        List<Tcsd> childList = mDb.tcsdDao().findChildByXmbh(main.getXmbh());

                        if (childList.size() > 0) {

                            List<MealChildGroup> mealChildGroupList = new ArrayList<>();
                            for (Tcsd t2 : childList) {
                                List<String> mealChildCateList = new ArrayList<>();

                                List<Tcsd> tcsdList = mDb.tcsdDao().findChild(t2.getTm(), t2.getXmbh());
                                for (Tcsd t : tcsdList) {
//                                    String mealChildCate = mDb.jyxmszDao().findLbmcByXmbh(t.getXmbh1());
//                                    if (!TextUtils.isEmpty(mealChildCate) && !mealChildCateList.contains(mealChildCate)) {
//                                        mealChildCateList.add(mealChildCate);
//                                    }
                                    if (!mealChildCateList.contains(t.getLbmc())) {
                                        mealChildCateList.add(t.getLbmc());
                                    }
                                }

                                mealChildGroupList.add(new MealChildGroup(mealChildCateList, tcsdList));
                            }

                            //
                            main.setJyxmsz(mDb.jyxmszDao().findByXmbh(main.getXmbh1()));
                            Meal meal = new Meal(main, mealChildGroupList);

                            FoodItem item = new FoodItem();
                            item.setFood(meal);

                            foodItemList.add(item);

                            // 保存套餐
                            if (!mMealAllList.contains(meal)) {
                                mMealAllList.add(meal);
                            }
                        } else {
                            // 只有套餐主项,没找到套餐子项
                            main.setJyxmsz(mDb.jyxmszDao().findByXmbh(main.getXmbh1()));
                            Meal meal = new Meal(main, null);

                            FoodItem item = new FoodItem();
                            item.setFood(meal);

                            foodItemList.add(item);

                            // 保存套餐
                            if (!mMealAllList.contains(meal)) {
                                mMealAllList.add(meal);
                            }
                        }
                    }
                }

                //
                Dmjyxmsslb d = mDb.dmjyxmsslbDao().findByLbmc(lbmc);
                if (foodItemList.size() > 0 && d != null) {
                    FoodItem header = new FoodItem();
                    header.setMenuItemType(MenuItemType.TYPE_HEADER);
                    header.setName(lbmc);

                    foodItemList.add(0, header);

                    FoodCate cate = new FoodCate(d);

                    header.setCateUuid(cate.getHeaderUuid());

                    mMenuMap.put(cate, foodItemList);

                    Collections.sort(foodItemList, mXlComparator);
                }
            }
        }

        // 口味
        handleTaste();
    }

    public int getCatePosition(UUID headerUuid) {
        Set<FoodCate> set = mMenuMap.keySet();
        List<FoodCate> list = new ArrayList<>(set);
        for (int i = 0; i < list.size(); i++) {
            FoodCate fc = list.get(i);
            if (Objects.equals(fc.getHeaderUuid(), headerUuid)) {
                return i;
            }
        }

        return -1;
    }

    /**
     * @param jyxmsz
     * @return Single 或 SingleAndMeals
     */
    @WorkerThread
    private FoodImpl createFood(Jyxmsz jyxmsz) {
        if (MealPosition.RECOMMEND == Settings.MEAL_POSITION) {
            // 推荐套餐
            // 查询当前单品是否在套餐中存在
            List<String> xmbhList;
            if (Settings.ONLY_SHOW_BY21) {
                xmbhList = mDb.tcsdDao().findByXmbh1By21(jyxmsz.getXmbh());

                // 判断套餐主项是否可用 (判断by21)
                List<String> newXmbhList = new ArrayList<>();
                for (String xmbh : xmbhList) {
                    Tcsd main = mDb.tcsdDao().findMainByXmbh(xmbh);
                    if (main != null) {
                        Jyxmsz jyxmsz1 = mDb.jyxmszDao().findByXmbh(main.getXmbh1());

                        if (jyxmsz1 != null && "1".equals(jyxmsz1.getBy21())) {
                            newXmbhList.add(xmbh);
                        }
                    }
                }
                xmbhList = newXmbhList;

            } else {
                xmbhList = mDb.tcsdDao().findByXmbh1(jyxmsz.getXmbh());
            }

            //
            if (xmbhList.size() == 0) {
                // 单品处理
                Single single = new Single(jyxmsz);
                mSingleAllList.add(single); // 保存单品

                return single;
            } else {
                // 单品和套餐处理
                SingleAndMeals singleAndMeals = new SingleAndMeals();

                // 添加单品
                Single single = new Single(jyxmsz);
                singleAndMeals.setSingle(single);

                // 处理套餐列表
                List<Meal> mealList = new ArrayList<>();
                for (String xmbh : xmbhList) {
                    Tcsd main = mDb.tcsdDao().findMainByXmbh(xmbh);
                    List<Tcsd> childList = mDb.tcsdDao().findChildByXmbh(xmbh);

                    if (main != null) {
                        if (childList.size() > 0) {
                            List<MealChildGroup> mealChildGroupList = new ArrayList<>();
                            for (Tcsd t2 : childList) {
                                List<String> mealChildCateList = new ArrayList<>();

                                List<Tcsd> tcsdList = mDb.tcsdDao().findChild(t2.getTm(), t2.getXmbh());
                                for (Tcsd t : tcsdList) {
//                                    String mealChildCate = db.jyxmszDao().findLbmcByXmbh(t.getXmbh1());
//                                    if (!TextUtils.isEmpty(mealChildCate) && !mealChildCateList.contains(mealChildCate)) {
//                                        mealChildCateList.add(mealChildCate);
//                                    }
                                    if (!mealChildCateList.contains(t.getLbmc())) {
                                        mealChildCateList.add(t.getLbmc());
                                    }
                                }

                                mealChildGroupList.add(new MealChildGroup(mealChildCateList, tcsdList));
                            }

                            //
                            main.setJyxmsz(mDb.jyxmszDao().findByXmbh(main.getXmbh1()));
                            Meal meal = new Meal(main, mealChildGroupList);
                            mealList.add(meal);

                            // 保存套餐
                            if (!mMealAllList.contains(meal)) {
                                mMealAllList.add(meal);
                            }
                        } else {
                            // 只有套餐主项,没找到套餐子项
                            main.setJyxmsz(mDb.jyxmszDao().findByXmbh(main.getXmbh1()));
                            Meal meal = new Meal(main, null);
                            mealList.add(meal);

                            // 保存套餐
                            if (!mMealAllList.contains(meal)) {
                                mMealAllList.add(meal);
                            }
                        }
                    }
                }
                singleAndMeals.setMealList(mealList);

                mSingleAllList.add(single); // 保存单品

                return singleAndMeals;
            }

        } else if (MealPosition.ALONE == Settings.MEAL_POSITION) {
            // 单品处理
            Single single = new Single(jyxmsz);
            mSingleAllList.add(single); // 保存单品

            return single;
        }

        return null;
    }

    public void setRefreshData() {
        mHandler.post(() -> {
            setChanged();
            notifyObservers();
        });
    }

    public List<FoodCate> getAllFoodCate() {
        return new ArrayList<>(mMenuMap.keySet());
    }

    public List<FoodItem> getAllFoodItem() {
        List<FoodItem> list = new ArrayList<>();

        for (Collection<FoodItem> list2 : mMenuMap.values()) {
            list.addAll(list2);
        }

        return list;
    }

    public int getFoodItemPosition(FoodCate cate) {
        int pos = -1;

        List<FoodItem> list = getAllFoodItem();
        for (int i = 0; i < list.size(); i++) {
            FoodItem item = list.get(i);
            if (MenuItemType.TYPE_HEADER == item.getMenuItemType()
                    && cate.getHeaderUuid().toString().equals(item.getCateUuid().toString())) {
                pos = i;
                break;
            }
        }

        return pos;
    }

    /**
     * 处理单品口味列表
     */
    @WorkerThread
    private void handleTaste() {
        // 单品口味
        for (Single s : mSingleAllList) {
            List<Dmpzsd> dmpzsdList = mDb.dmpzsdDao().findByDmkwdydpXmbh(s.getItem().getXmbh());
            if (dmpzsdList.size() > 0) {
                s.setTasteList(dmpzsdList);
            }
        }

        // 套餐子项口味
        for (Meal meal : mMealAllList) {
            List<MealChildGroup> mealChildGroupList = meal.getMealChildGroupList();
            if (mealChildGroupList != null) {
                for (MealChildGroup mcg : mealChildGroupList) {
                    List<Tcsd> tcsdList = mcg.getChildList();
                    for (Tcsd t : tcsdList) {
                        List<Dmpzsd> dmpzsdList = mDb.dmpzsdDao().findByDmkwdydpXmbh(t.getXmbh1());
                        if (dmpzsdList.size() > 0) {
                            List<Taste> tasteList = new ArrayList<>();
                            for (Dmpzsd d : dmpzsdList) {
                                tasteList.add(new Taste(d));
                            }
                            t.setTasteList(tasteList);
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理买赠/加价促销(实时计算)
     */
    @WorkerThread
    public void computeMzszjbxxAndMzszmxxx() {
        long currentTime = System.currentTimeMillis();
        List<Mzszjbxx> mzszjbxxList = mDb.mzszjbxxDao().findAll();
        LocalDateTime now = SqlServerDateTime.getInstance().getNowServerDateTime();

        for (Mzszjbxx mj : mzszjbxxList) {
            // 判断开始日期时间、结束日期时间
            if (mj.getKsrq() != null && mj.getKsrq().plusDays(-1).isBefore(now.toLocalDate())
                    && mj.getJsrq() != null && mj.getJsrq().plusDays(1).isAfter(now.toLocalDate())
                    && mj.getKssj() != null && mj.getKssj().isBefore(now.toLocalTime())
                    && mj.getJssj() != null && mj.getJssj().isAfter(now.toLocalTime())) {

                int week = now.getDayOfWeek();
                try {
                    Method method = mj.getClass().getMethod("getZ" + week);
                    Object val = method.invoke(mj);

                    // 判断今天是否启用
                    if ("1".equals(val)) {
                        List<Mzszmxxx> mzszmxxxList = mDb.mzszmxxxDao().findByBm(mj.getBm());

                        if ("1".equals(mj.getJbby1())
                                && mj.getJbby3() != null && mj.getJbby3() == 1) {
                            // 买赠

                            List<Jyxmsz> jyxmszList = new ArrayList<>();
                            for (Mzszmxxx mm : mzszmxxxList) {
                                Jyxmsz jyxmsz = mDb.jyxmszDao().findByXmbh(mm.getXmbh());
                                if (jyxmsz != null) {
                                    jyxmsz.setXsjg(0f);

                                    if (mm.getSl() != null) {
                                        jyxmsz.setSl(mm.getSl());
                                    } else {
                                        jyxmsz.setSl(1);
                                    }

                                    jyxmszList.add(jyxmsz);
                                }
                            }

                            //
                            if (jyxmszList.size() > 0) {
                                for (Single s : mSingleAllList) {
                                    if (mj.getXmbh().equals(s.getItem().getXmbh())) {
                                        s.setPresentList(jyxmszList);
                                        s.setCurrentTimePresent(currentTime);
                                        break;
                                    }
                                }
                            }

                        } else if ("2".equals(mj.getJbby1())) {
                            // 加价促销

                            List<Jyxmsz> jyxmszList = new ArrayList<>();
                            for (Mzszmxxx mm : mzszmxxxList) {
                                Jyxmsz jyxmsz = mDb.jyxmszDao().findByXmbh(mm.getXmbh());
                                if (jyxmsz != null) {
                                    jyxmsz.setXsjg(mm.getXsjg());

                                    if (mm.getSl() != null) {
                                        jyxmsz.setSl(mm.getSl());
                                    } else {
                                        jyxmsz.setSl(1);
                                    }

                                    jyxmszList.add(jyxmsz);
                                }
                            }

                            //
                            if (jyxmszList.size() > 0) {
                                for (Single s : mSingleAllList) {
                                    if (mj.getXmbh().equals(s.getItem().getXmbh())) {
                                        s.setAddPriceList(jyxmszList);
                                        s.setCurrentTimeAddPrice(currentTime);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                } catch (Exception e) {
                    Log.e(TAG, "computeMzszjbxxAndMzszmxxx: ", e);
                }
            }
        }

        // 清空飞当前的赠送和加价
        for (Single s : mSingleAllList) {
            if (currentTime != s.getCurrentTimePresent()) {
                s.setPresentList(null);
            }

            if (currentTime != s.getCurrentTimeAddPrice()) {
                s.setAddPriceList(null);
            }
        }
    }

    /**
     * 计算促销单明细信息<br>
     */
    @WorkerThread
    public void computeCxdmxxx() {
        List<Single> changedList = new ArrayList<>();

        LocalDateTime now = SqlServerDateTime.getInstance().getNowServerDateTime();

        List<Cxdmxxx> cxdmxxxList = mDb.cxdmxxxDao().findAll();
        for (Cxdmxxx c : cxdmxxxList) {

            Jyxmsz jyxmsz = mDb.jyxmszDao().findByXmbh(c.getXmbh());
            if (jyxmsz != null) {

                if (c.getKsrq() != null && c.getKsrq().plusDays(-1).isBefore(now.toLocalDate())
                        && c.getJsrq() != null && c.getJsrq().plusDays(1).isAfter(now.toLocalDate())
                        && c.getKssj() != null && c.getKssj().isBefore(now.toLocalTime())
                        && c.getJssj() != null && c.getJssj().isAfter(now.toLocalTime())) {

                    int week = now.getDayOfWeek();
                    try {
                        Method method = c.getClass().getMethod("getZ" + week);
                        Object val = method.invoke(c);

                        if ("1".equals(val)) {
                            for (Single s : mSingleAllList) {

                                if (Objects.equals(s.getItem().getXmbh(), jyxmsz.getXmbh())) {
                                    changedList.add(s);

                                    if ("1".equals(c.getBz())) {
                                        //noinspection UnnecessaryBoxing
                                        if (!Objects.equals(s.getHourDiscountPrice(), Float.valueOf(0))) {
                                            Log.d(TAG, "computeCxdmxxx: 发现赠送");

                                            s.setHourDiscount(true);
                                            s.setHourDiscountPrice(0f);
                                        }

                                    } else {
                                        if (!Objects.equals(s.getHourDiscountPrice(), c.getXsjgzhj())) {
                                            Log.d(TAG, "computeCxdmxxx: 发现折后价");

                                            s.setHourDiscount(true);
                                            s.setHourDiscountPrice(c.getXsjgzhj());
                                        }
                                    }

                                    break;
                                }
                            }
                        }

                    } catch (Exception e) {
                        Log.e(TAG, "computeCxdmxxx: ", e);
                    }
                }
            }
        }

        //
        for (Single s : mSingleAllList) {
            if (!changedList.contains(s)) {
                if (s.isHourDiscount()) {
                    s.setHourDiscount(false);
                    s.setHourDiscountPrice(null);
                }
            }
        }
    }

    /**
     * 查询单品
     */
    public void querySingle(String xmbh, OnQueryEndListener<Single> listener) {
        new Thread(() -> {
            for (FoodItem fi : getAllFoodItem()) {
                if (fi.getFood() instanceof Single) {
                    Single single = (Single) fi.getFood();

                    if (xmbh.equals(single.getItem().getXmbh())) {
                        mHandler.post(() -> listener.onQueryEnd(single));
                        return;
                    }
                }
            }

            mHandler.post(() -> listener.onQueryEnd(null));

        }).start();
    }

    /**
     * 查询单品套餐
     */
    public void querySingleAndMeals(String xmbh, OnQueryEndListener<SingleAndMeals> listener) {
        new Thread(() -> {
            for (FoodItem fi : getAllFoodItem()) {
                if (fi.getFood() instanceof SingleAndMeals) {
                    SingleAndMeals singleAndMeals = (SingleAndMeals) fi.getFood();

                    if (xmbh.equals(singleAndMeals.getSingle().getItem().getXmbh())) {
                        mHandler.post(() -> listener.onQueryEnd(singleAndMeals));
                        return;
                    }
                }
            }

            mHandler.post(() -> listener.onQueryEnd(null));

        }).start();
    }

    /**
     * 查询套餐
     */
    public void queryMeal(String xmbh1, @NonNull OnQueryEndListener<Meal> listener) {
        new Thread(() -> {
            for (Meal m : mMealAllList) {
                if (m.getMainTcsd().getXmbh1().equals(xmbh1)) {
                    mHandler.post(() -> listener.onQueryEnd(m));
                    return;
                }
            }

            mHandler.post(() -> listener.onQueryEnd(null));

        }).start();
    }

    /**
     * 查询单品组
     */
    public void querySingleGroup(String no, OnQueryEndListener<SingleGroup> listener) {
        new Thread(() -> {
            for (SingleGroup sg : mSingleGroupAllList) {
                if (sg.getNo().equals(no)) {

                    mHandler.post(() -> listener.onQueryEnd(sg));
                    return;
                }
            }

            mHandler.post(() -> listener.onQueryEnd(null));

        }).start();
    }

    public interface OnQueryEndListener<T> {
        void onQueryEnd(T t);
    }
}
